{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# William Toolbox OpenAPI 接口测试\n",
    "\n",
    "这个notebook用于测试William Toolbox的公开API接口，主要测试以下几个接口：\n",
    "\n",
    "1. 获取OpenAI兼容服务信息\n",
    "2. 获取可用的RAG列表\n",
    "3. 获取可用的模型列表\n",
    "\n",
    "这些接口都需要API Key进行认证。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "import json\n",
    "from pprint import pprint"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 配置测试环境\n",
    "\n",
    "首先我们需要设置基础URL和API Key。请确保你已经在William Toolbox中创建了API Key。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 配置\n",
    "BASE_URL = \"http://localhost:8005\"  # 根据你的实际部署情况修改\n",
    "API_KEY = \"sk-2cf1c6d22c1e480f8a17820653e8c651\"    # 替换为你的实际API Key\n",
    "\n",
    "# 设置通用请求头\n",
    "headers = {\n",
    "    \"Authorization\": f\"Bearer {API_KEY}\",\n",
    "    \"Content-Type\": \"application/json\"\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 测试获取OpenAI兼容服务信息\n",
    "\n",
    "这个接口不需要API Key认证，可以直接访问。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ 成功获取OpenAI兼容服务信息\n",
      "{'host': None, 'isRunning': False, 'port': None}\n"
     ]
    }
   ],
   "source": [
    "def test_openai_compatible_service_info():\n",
    "    url = f\"{BASE_URL}/api/public/openai-compatible-service-info\"\n",
    "    response = requests.get(url)\n",
    "    \n",
    "    if response.status_code == 200:\n",
    "        print(\"✅ 成功获取OpenAI兼容服务信息\")\n",
    "        pprint(response.json())\n",
    "    else:\n",
    "        print(f\"❌ 请求失败: {response.status_code}\")\n",
    "        print(response.text)\n",
    "    \n",
    "    return response.json() if response.status_code == 200 else None\n",
    "\n",
    "openai_service_info = test_openai_compatible_service_info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 测试获取可用的RAG列表\n",
    "\n",
    "这个接口需要API Key认证。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ 成功获取RAG列表\n",
      "共有 25 个RAG\n",
      "- doc_repo\n",
      "- Ray文档知识库\n",
      "- 计算增强RAG\n",
      "- 计算增强-思考增强RAG\n",
      "- 通用模型计算增强\n",
      "- 通用模型计算增强-2型\n",
      "- 训练测试WORD-脱敏版\n",
      "- 通用模型计算增强-deepseek\n",
      "- 通用模型增强-深度思考\n",
      "- 电影Schema\n",
      "- ByzerSQL文档\n",
      "- NextJs文档\n",
      "- 银联训练数据RAG\n",
      "- auto-coder.web-repos\n",
      "- 通用模型计算增强-sonnet\n",
      "- mcp-docs\n",
      "- mcp-python-sdk\n",
      "- kyligence-docs\n",
      "- 小微贷知识库\n",
      "- luke-test\n",
      "- 批注知识库\n",
      "- 自动批注-doubao\n",
      "- 申宏\n",
      "- 超大知识库\n",
      "- 测试文档\n"
     ]
    }
   ],
   "source": [
    "def test_available_rags():\n",
    "    url = f\"{BASE_URL}/api/public/available-rags\"\n",
    "    response = requests.get(url, headers=headers)\n",
    "    \n",
    "    if response.status_code == 200:\n",
    "        print(\"✅ 成功获取RAG列表\")\n",
    "        rags = response.json()\n",
    "        print(f\"共有 {len(rags)} 个RAG\")\n",
    "        for rag in rags:\n",
    "            print(f\"- {rag['name']}\")\n",
    "    else:\n",
    "        print(f\"❌ 请求失败: {response.status_code}\")\n",
    "        print(response.text)\n",
    "    \n",
    "    return response.json() if response.status_code == 200 else None\n",
    "\n",
    "rags = test_available_rags()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 测试获取可用的模型列表\n",
    "\n",
    "这个接口需要API Key认证。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ 成功获取模型列表\n",
      "共有 20 个模型\n",
      "- deepseek_chat (状态: running)\n",
      "- sonnet_3_5_chat (状态: stopped)\n",
      "- qwen_vl (状态: stopped)\n",
      "- emb (状态: running)\n",
      "- example_rag_chat (状态: stopped)\n",
      "- qwen2_72b_chat (状态: stopped)\n",
      "- stable_deepseek_chat (状态: stopped)\n",
      "- kyligence_ai (状态: stopped)\n",
      "- qwen2_5_128k_chat (状态: stopped)\n",
      "- qwen110b_chat (状态: stopped)\n",
      "- flux_chat (状态: stopped)\n",
      "- kyligence_enhance_model (状态: stopped)\n",
      "- power_kyligence_enhance_model (状态: stopped)\n",
      "- doubao_128k_chat (状态: stopped)\n",
      "- deepseek_vl (状态: stopped)\n",
      "- qvq_vl (状态: stopped)\n",
      "- doubao_r1_chat (状态: stopped)\n",
      "- v_r1_chat (状态: running)\n",
      "- r1_chat (状态: running)\n",
      "- v3_chat (状态: running)\n"
     ]
    }
   ],
   "source": [
    "def test_available_models():\n",
    "    url = f\"{BASE_URL}/api/public/available-models\"\n",
    "    response = requests.get(url, headers=headers)\n",
    "    \n",
    "    if response.status_code == 200:\n",
    "        print(\"✅ 成功获取模型列表\")\n",
    "        models = response.json()\n",
    "        print(f\"共有 {len(models)} 个模型\")\n",
    "        for model in models:\n",
    "            print(f\"- {model['name']} (状态: {model['status']})\")\n",
    "    else:\n",
    "        print(f\"❌ 请求失败: {response.status_code}\")\n",
    "        print(response.text)\n",
    "    \n",
    "    return response.json() if response.status_code == 200 else None\n",
    "\n",
    "models = test_available_models()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 综合测试结果分析\n",
    "\n",
    "下面我们对测试结果进行一些分析。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def analyze_results():\n",
    "    print(\"==== 测试结果分析 ====\\n\")\n",
    "    \n",
    "    # 分析OpenAI兼容服务\n",
    "    if openai_service_info:\n",
    "        if openai_service_info.get('isRunning'):\n",
    "            print(f\"✅ OpenAI兼容服务正在运行 - 地址: {openai_service_info.get('host')}:{openai_service_info.get('port')}\")\n",
    "        else:\n",
    "            print(\"⚠️ OpenAI兼容服务未运行\")\n",
    "    else:\n",
    "        print(\"❌ 无法获取OpenAI兼容服务信息\")\n",
    "    \n",
    "    # 分析RAG列表\n",
    "    if rags is not None:\n",
    "        if len(rags) > 0:\n",
    "            print(f\"✅ 系统中有 {len(rags)} 个可用的RAG\")\n",
    "        else:\n",
    "            print(\"⚠️ 系统中没有配置任何RAG\")\n",
    "    else:\n",
    "        print(\"❌ 无法获取RAG列表，可能是API Key无效或权限不足\")\n",
    "    \n",
    "    # 分析模型列表\n",
    "    if models is not None:\n",
    "        if len(models) > 0:\n",
    "            running_models = [m for m in models if m.get('status') == 'running']\n",
    "            print(f\"✅ 系统中有 {len(models)} 个模型，其中 {len(running_models)} 个正在运行\")\n",
    "        else:\n",
    "            print(\"⚠️ 系统中没有配置任何模型\")\n",
    "    else:\n",
    "        print(\"❌ 无法获取模型列表，可能是API Key无效或权限不足\")\n",
    "\n",
    "analyze_results()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 测试API Key创建流程\n",
    "\n",
    "以下是如何通过管理员账号创建API Key的示例代码。注意这需要管理员权限。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def login_and_create_api_key():\n",
    "    # 1. 登录获取JWT Token\n",
    "    login_url = f\"{BASE_URL}/auth/login\"\n",
    "    login_data = {\n",
    "        \"username\": \"admin\",  # 替换为你的管理员用户名\n",
    "        \"password\": \"admin\"   # 替换为你的管理员密码\n",
    "    }\n",
    "    \n",
    "    login_response = requests.post(login_url, json=login_data)\n",
    "    if login_response.status_code != 200:\n",
    "        print(f\"❌ 登录失败: {login_response.status_code}\")\n",
    "        print(login_response.text)\n",
    "        return None\n",
    "    \n",
    "    token = login_response.json().get('token')\n",
    "    print(\"✅ 登录成功，获取到JWT Token\")\n",
    "    \n",
    "    # 2. 创建API Key\n",
    "    create_key_url = f\"{BASE_URL}/api-keys\"\n",
    "    create_key_headers = {\n",
    "        \"Authorization\": f\"Bearer {token}\",\n",
    "        \"Content-Type\": \"application/json\"\n",
    "    }\n",
    "    create_key_data = {\n",
    "        \"name\": \"Test API Key\",\n",
    "        \"description\": \"Created from Jupyter notebook for testing\",\n",
    "        \"expires_in_days\": 7\n",
    "    }\n",
    "    \n",
    "    create_key_response = requests.post(create_key_url, headers=create_key_headers, json=create_key_data)\n",
    "    if create_key_response.status_code != 200:\n",
    "        print(f\"❌ 创建API Key失败: {create_key_response.status_code}\")\n",
    "        print(create_key_response.text)\n",
    "        return None\n",
    "    \n",
    "    api_key_info = create_key_response.json()\n",
    "    print(\"✅ 成功创建API Key\")\n",
    "    print(f\"API Key: {api_key_info['key']}\")\n",
    "    print(f\"名称: {api_key_info['name']}\")\n",
    "    print(f\"创建时间: {api_key_info['created_at']}\")\n",
    "    print(f\"过期时间: {api_key_info['expires_at']}\")\n",
    "    \n",
    "    return api_key_info\n",
    "\n",
    "# 取消注释下面的行来运行API Key创建流程\n",
    "# new_api_key = login_and_create_api_key()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使用新创建的API Key测试接口\n",
    "\n",
    "如果你创建了新的API Key，可以使用它来测试接口。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test_with_new_api_key(api_key_info):\n",
    "    if not api_key_info:\n",
    "        print(\"❌ 没有可用的API Key信息\")\n",
    "        return\n",
    "    \n",
    "    new_api_key = api_key_info['key']\n",
    "    new_headers = {\n",
    "        \"Authorization\": f\"Bearer {new_api_key}\",\n",
    "        \"Content-Type\": \"application/json\"\n",
    "    }\n",
    "    \n",
    "    print(\"\\n==== 使用新API Key测试RAG列表接口 ====\\n\")\n",
    "    url = f\"{BASE_URL}/api/public/available-rags\"\n",
    "    response = requests.get(url, headers=new_headers)\n",
    "    \n",
    "    if response.status_code == 200:\n",
    "        print(\"✅ 使用新API Key成功获取RAG列表\")\n",
    "        rags = response.json()\n",
    "        print(f\"共有 {len(rags)} 个RAG\")\n",
    "    else:\n",
    "        print(f\"❌ 请求失败: {response.status_code}\")\n",
    "        print(response.text)\n",
    "\n",
    "# 如果你运行了API Key创建流程，可以取消注释下面的行来测试新API Key\n",
    "# test_with_new_api_key(new_api_key)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "byzerllm",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
